﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Collections;

namespace Ecommerce.Model
{
    public class ProdutoModel : BaseData, IEqualityComparer<tb_pro_produto>
    {
        public void Inserir(tb_pro_produto produto)
        {
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                produto.tb_cat_categoria = (from n in db.tb_cat_categoria where n.cat_idt_categoria.Equals(produto.tb_cat_categoria.cat_idt_categoria) select n).FirstOrDefault();
                db.tb_pro_produto.Add(produto);
                
                //TODO: Remover
                try
                {
                    db.SaveChanges();
                }
                catch (System.Data.Entity.Validation.DbEntityValidationException ex)
                {
                    for (int i = 0; i < ex.EntityValidationErrors.Count(); i++)
                    {
                        string a = "";
                    }
                    throw ex;
                }
            }
        }

        public void Editar(tb_pro_produto produto)
        {
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                db.tb_cat_categoria.Attach(produto.tb_cat_categoria);
                db.tb_pro_produto.Attach(produto);

                db.Entry(produto).State = System.Data.EntityState.Modified;
                db.Entry(produto.tb_cat_categoria).State = System.Data.EntityState.Modified;

                try
                {
                    db.SaveChanges();
                }
                catch (System.Data.Entity.Validation.DbEntityValidationException ex)
                {
                    foreach (var validationErrors in ex.EntityValidationErrors)
                        foreach (var validationError in validationErrors.ValidationErrors)
                            Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
                }
                catch (System.Data.Entity.Infrastructure.DbUpdateException DbUEx)
                {
                    throw DbUEx;
                }
            }
        }

        public List<tb_pro_produto> Listar()
        {
            List<tb_pro_produto> produtos;

            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                produtos = (from n in db.tb_pro_produto.Include("tb_cat_categoria") where n.pro_flg_ativo.Equals(true) orderby n.pro_nom_produto select n).ToList();
            }

            return produtos;
        }

        public List<tb_pro_produto> Listar(FiltroProdutoModel filtro)
        {
            List<tb_pro_produto> produtos;

            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                produtos = db.tb_pro_produto
                            .Include("tb_cat_categoria")
                            .Where(x => !String.IsNullOrEmpty(filtro.NomeProduto) ? x.pro_nom_produto.Contains(filtro.NomeProduto) : 1 == 1 &&
                                        !String.IsNullOrEmpty(filtro.CodigoProduto) ? x.pro_cod_produto.Equals(filtro.CodigoProduto) : 1 == 1 &&
                                        filtro.IdentificadorCategoria.HasValue ? x.cat_idt_categoria == filtro.IdentificadorCategoria.Value : 1 == 1
                            ).OrderBy(x=> x.pro_nom_produto).ToList();
            }

            return produtos;
        }

        public tb_pro_produto Obter(int identificador)
        {
            tb_pro_produto produto;

            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                produto = (from n in db.tb_pro_produto.Include("tb_cat_categoria") where n.pro_idt_produto.Equals(identificador) select n).FirstOrDefault();
            }
            return produto;
        }

        public void InserirImagem(tb_ipr_imagem_produto imagem)
        {
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                db.tb_ipr_imagem_produto.Add(imagem);
                db.SaveChanges();
            }
        }

        public void ExcluirImagem(int identificadorProduto)
        {
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                var imagem = (from n in db.tb_ipr_imagem_produto where n.ipr_idt_imagem_produto.Equals(identificadorProduto) select n).FirstOrDefault();

                File.Delete(imagem.ipr_des_caminho_imagem);
                
                db.tb_ipr_imagem_produto.Remove(imagem);
                db.SaveChanges();
            }
        }

        public List<tb_ipr_imagem_produto> ListarImagem(int identificadorProduto)
        {
            List<tb_ipr_imagem_produto> imagens;

            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                imagens = (from n in db.tb_ipr_imagem_produto where n.pro_idt_produto.Equals(identificadorProduto) select n).ToList();
            }
            return imagens;
        }

        public List<tb_pro_produto> ListarDestaqueHome()
        {
            List<tb_pro_produto> produtos;

            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                produtos = db.tb_pro_produto.Include("tb_ipr_imagem_produto").Include("tb_des_desconto").Include("tb_cat_categoria").Where(x => x.pro_flg_ativo == true && x.pro_flg_exibir_pagina_inicial == true).ToList();
            }

            return produtos;
        }

        public tb_pro_produto ObterPorCodigo(string codigo)
        {
            tb_pro_produto produto;

            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                produto = db.tb_pro_produto.Include("tb_ipr_imagem_produto").Include("tb_des_desconto").Include("tb_cat_categoria").Where(x => x.pro_cod_produto.Equals(codigo)).FirstOrDefault();
            }
            return produto;
        }

        public List<tb_pro_produto> ListarProdutosRelacionados(int indentificadorProduto)
        {
            List<tb_pro_produto> produtos;

            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                int[] produtosAssociados = db.tb_prr_produto_relacionado.Where(x => x.pro_idt_produto_principal == indentificadorProduto).Select(x => x.pro_idt_produto_associado).ToArray();
                produtos = db.tb_pro_produto.Include("tb_ipr_imagem_produto").Include("tb_des_desconto").Include("tb_cat_categoria").Where(x => produtosAssociados.Contains(x.pro_idt_produto)).OrderBy(x => x.pro_nom_produto).ToList();
            }

            return produtos;
        }

        public List<tb_pro_produto> ListarProdutosVendaCruzada(int indentificadorProduto)
        {
            List<tb_pro_produto> produtos;

            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                int[] produtosAssociados = db.tb_pvc_produto_venda_cruzada.Where(x => x.pro_idt_produto_principal == indentificadorProduto).Select(x => x.pro_idt_produto_associado).ToArray();
                produtos = db.tb_pro_produto.Include("tb_ipr_imagem_produto").Include("tb_des_desconto").Include("tb_cat_categoria").Where(x => produtosAssociados.Contains(x.pro_idt_produto)).OrderBy(x => x.pro_nom_produto).ToList();
            }

            return produtos;
        }

        public List<tb_pro_produto> ListarProdutosVendaCruzadaNaoAssociados(int indentificadorProduto)
        {
            List<tb_pro_produto> produtos;

            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                int[] produtosAssociados = db.tb_pvc_produto_venda_cruzada.Where(x => x.pro_idt_produto_principal == indentificadorProduto).Select(x => x.pro_idt_produto_associado).ToArray();
                produtos = db.tb_pro_produto.Include("tb_ipr_imagem_produto").Include("tb_des_desconto").Include("tb_cat_categoria").Where(x => !produtosAssociados.Contains(x.pro_idt_produto)).OrderBy(x => x.pro_nom_produto).ToList();
            }

            return produtos;
        }

        public void InserirProdutoVendaCruzada(List<tb_pvc_produto_venda_cruzada> produtos, int idtProdutoPrincipal)
        {
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                foreach (tb_pvc_produto_venda_cruzada item in produtos)
                {
                    db.tb_pvc_produto_venda_cruzada.Add(item);
                    db.Entry(item).State = System.Data.EntityState.Added;
                    db.SaveChanges();
                }
            }
        }

        public void ExcluirProdutoVendaCruzadaAssociado(int idtProdPrincipal, int idtProdAssociado)
        {
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                var q = (from pvc in db.tb_pvc_produto_venda_cruzada select pvc).ToList();

                foreach (tb_pvc_produto_venda_cruzada item in q)
                {
                    var associacao = (from a in q where a.pro_idt_produto_principal.Equals(idtProdPrincipal) && a.pro_idt_produto_associado.Equals(idtProdAssociado) select a).FirstOrDefault();
                    db.tb_pvc_produto_venda_cruzada.Remove(associacao);
                }
                db.SaveChanges();
            }
        }

        public List<tb_pro_produto> ListarPorCategoria(int[] categorias)
        {
            List<tb_pro_produto> produtos;

            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                produtos = db.tb_pro_produto.Include("tb_ipr_imagem_produto").Include("tb_des_desconto").Include("tb_cat_categoria").Where(x => x.pro_flg_ativo == true && categorias.Contains(x.cat_idt_categoria)).ToList();
            }

            return produtos;
        }

        public static decimal CalcularDesconto(tb_pro_produto produto, bool revenda, int identificadorFormaPagamento, decimal valorProduto) 
        {
            tb_des_desconto desconto = produto.tb_des_desconto.Where(x => x.tpa_idt_tipo_pagamento == identificadorFormaPagamento && x.des_flg_desconto_revenda == revenda && (DateTime.Now >= x.des_dat_inicio_vigencia &&  DateTime.Now <= x.des_dat_fim_vigencia)).FirstOrDefault();
            decimal multiplicador = decimal.Parse("0,01");
            if (desconto != null)
                return valorProduto - (desconto.des_vlr_desconto * multiplicador * valorProduto);
            else
                return valorProduto;
        }

        public List<tb_pro_produto> ListarProdutosRelacionadosAssociados(int indentificadorProduto)
        {
            List<tb_pro_produto> produtos;

            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                int[] produtosAssociados = db.tb_prr_produto_relacionado.Where(x => x.pro_idt_produto_principal == indentificadorProduto).Select(x => x.pro_idt_produto_associado).ToArray();
                produtos = db.tb_pro_produto.Include("tb_ipr_imagem_produto").Include("tb_des_desconto").Include("tb_cat_categoria").Where(x => produtosAssociados.Contains(x.pro_idt_produto)).OrderBy(x => x.pro_nom_produto).ToList();
            }

            return produtos;
        }

        public List<tb_pro_produto> ListarProdutosRelacionadosNaoAssociados(int indentificadorProduto)
        {
            List<tb_pro_produto> produtos;

            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                int[] produtosAssociados = db.tb_prr_produto_relacionado.Where(x => x.pro_idt_produto_principal == indentificadorProduto).Select(x => x.pro_idt_produto_associado).ToArray();
                produtos = db.tb_pro_produto.Include("tb_ipr_imagem_produto").Include("tb_des_desconto").Include("tb_cat_categoria").Where(x => !produtosAssociados.Contains(x.pro_idt_produto)).OrderBy(x => x.pro_nom_produto).ToList();
            }

            return produtos;
        }

        public void InserirProdutoRelacionado(List<tb_prr_produto_relacionado> produtos, int idtProdutoPrincipal)
        {
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                foreach (tb_prr_produto_relacionado item in produtos)
                {
                    db.tb_prr_produto_relacionado.Add(item);
                    db.Entry(item).State = System.Data.EntityState.Added;
                    db.SaveChanges();
                }
            }
        }

        public void ExcluirProdutoRelacionadoAssociado(int idtProdPrincipal, int idtProdAssociado)
        {
            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                var q = (from prr in db.tb_prr_produto_relacionado select prr).ToList();

                foreach (tb_prr_produto_relacionado item in q)
                {
                    var associacao = (from a in q where a.pro_idt_produto_principal.Equals(idtProdPrincipal) && a.pro_idt_produto_associado.Equals(idtProdAssociado) select a).FirstOrDefault();
                    db.tb_prr_produto_relacionado.Remove(associacao);
                }
                db.SaveChanges();
            }
        }

        public List<tb_pro_produto> ListarPorNome(string nome)
        {
            List<tb_pro_produto> produtos;

            using (EcommerceEntities db = new EcommerceEntities(this.InicializarStringConexao(), false))
            {
                produtos = db.tb_pro_produto.Include("tb_ipr_imagem_produto").Include("tb_des_desconto").Include("tb_cat_categoria").Where(x => x.pro_flg_ativo == true && (x.pro_des_produto.Contains(nome) || x.pro_cod_produto.Contains(nome) || x.pro_des_abreviada.Contains(nome) || x.pro_nom_produto.Contains(nome))).ToList();
            }

            produtos = produtos.Distinct(this).ToList();

            return produtos;
        }

        public bool Equals(tb_pro_produto x, tb_pro_produto y)
        {
            return x.pro_idt_produto.Equals(y.pro_idt_produto);
        }

        public int GetHashCode(tb_pro_produto obj)
        {
            return obj.pro_idt_produto.GetHashCode();

        }
    }
}